﻿// $ PURE $ // class name and mean

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Windows.Forms;
using System.Drawing;

namespace CodeTable
{
    partial class GridView // TODO: optimize view controls - create and update only visible controls
    {
        private Hashtable hashtable = new Hashtable();
        private CodeTable owner;
        private BlockRender blockRender;
        private BlockInput blockInput;
        private Panel bottomRightMarker;

        public GridView(CodeTable owner, BlockRender blockRender, BlockInput blockInput, Panel bottomRightMarker) // TODO: remove owner and other HACK stuff
        {
            this.owner = owner;
            this.blockRender = blockRender;
            this.blockInput = blockInput;
            this.bottomRightMarker = bottomRightMarker;
        }

        private GridView.Block AddViewControl(object hash, Point gridCoordinate, string codeText)
        {
            GridView.Block codeBlockView = new GridView.Block(
                blockRender.GetCodeImage(codeText),
                gridCoordinate
            );
            codeBlockView.MouseClick += new MouseEventHandler(owner.CodeBlockView_MouseClick);
            owner.Controls.Add(codeBlockView);

            // place block view in grid view
            hashtable.Add(hash, codeBlockView);
            return codeBlockView;
        }

        public void GridData_BlockChanged(object sender, BlockEventArgs e)
        {
            string hash = "R" + e.gridCoordinate.Y.ToString() + "C" + e.gridCoordinate.X.ToString(); // TODO: use common hash algorithm
            GridView.Block block = hashtable[hash] as GridView.Block;

            if (e.codeText != string.Empty)
            {
                if (block == null)
                {
                    block = AddViewControl(hash, e.gridCoordinate, e.codeText);
                    RefreshViewControlLocation(block);
                }
                else
                {
                    if (blockInput.Visible && e.gridCoordinate == blockInput.CurrentGridCoordinate)
                    {
                        blockInput.needRefreshImage = true;
                    }
                    else
                    {
                        block.Image = blockRender.GetCodeImage(e.codeText);
                    }
                }
            }
            else
            {
                if (block != null)
                {
                    owner.Controls.Remove(block);
                    hashtable.Remove(hash);
                    block.Dispose();
                }
            }

            if (e.needsRefresh)
            {
                RefreshViewControlsLocations();
                owner.Invalidate();
            }
        }

        public void GridData_GridChanged(object sender, EventArgs e)
        {
            // HACK // TODO: remove in future
            foreach (DictionaryEntry entry in hashtable)
            {
                Control control = entry.Value as Block;
                owner.Controls.Remove(control);
            }
            hashtable.Clear();
            GridEventArgs ge = e as GridEventArgs;
            if (ge.stringHashtable != null)
            {
                foreach (DictionaryEntry entry in ge.stringHashtable)
                {
                    string hash = entry.Key as string;
                    string text = entry.Value as string;
                    Point gridCoordinate = DataSources.Utils.Hash2GridCoordinate(hash);
                    AddViewControl(hash, gridCoordinate, text);
                }
            }
            //

            RefreshViewControlsLocations();
            owner.Invalidate();
        }

        private void RefreshViewControlLocation(GridView.Block block)
        {
            Point newLocation = owner.GetLocationByGridCoordinate(block.GridCoordinate);
            newLocation.Offset(owner.AutoScrollPosition);
            block.Location = newLocation;
        }

        private void RefreshViewControlsLocations()
        {
            // marker location
            Size totalSize = owner.TotalSize;
            bottomRightMarker.Location = new Point(
                totalSize.Width - bottomRightMarker.Size.Width + owner.AutoScrollPosition.X,
                totalSize.Height - bottomRightMarker.Size.Height + owner.AutoScrollPosition.Y
            );

            // view controls location
            foreach (System.Collections.DictionaryEntry codeBlockEntry in hashtable)
            {
                GridView.Block block = codeBlockEntry.Value as GridView.Block;
                RefreshViewControlLocation(block);
            }
        }
    }
}
